package com.lsh.payment.core.service.cmpay.impl;

import com.alibaba.fastjson.JSON;
import com.lsh.payment.api.model.basevo.ExceptionStatus;
import com.lsh.payment.api.model.cmpay.CmNotifyRequest;
import com.lsh.payment.core.exception.BusinessException;
import com.lsh.payment.core.model.payasync.EmailModel;
import com.lsh.payment.core.model.payenum.OperateStatus;
import com.lsh.payment.core.model.payenum.PayStatus;
import com.lsh.payment.core.model.payenum.cmpay.CmBizOrderStatus;
import com.lsh.payment.core.model.payment.PayDeal;
import com.lsh.payment.core.service.async.PayEventBus;
import com.lsh.payment.core.service.cmpay.IcmNotifyService;
import com.lsh.payment.core.service.email.EmailConfig;
import com.lsh.payment.core.service.payment.impl.PayBaseService;
import com.lsh.payment.core.service.payment.impl.PayDealService;
import com.lsh.payment.core.util.BigDecimalUtils;
import com.lsh.payment.core.util.PayAssert;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * Project Name: lsh-payment
 *
 * @author peter
 * @date 19/4/17
 * 北京链商电子商务有限公司
 * Package
 * desc:
 */
@Service
@Slf4j
public class CmNotifyServiceImpl implements IcmNotifyService {

    @Autowired
    private PayDealService payDealService;

    @Autowired
    private PayBaseService payBaseService;

    @Autowired
    private EmailConfig emailConfig;

    /**
     * 微信回调接口
     *
     * @param cmNotify
     */
    @Override
    public void cmNotify(CmNotifyRequest cmNotify) {

        String clientSn2payPaymentNo = cmNotify.getClient_sn();
        String orderStatus = cmNotify.getOrder_status();

        PayDeal payDeal = payDealService.queryPayDealByPayPaymentNo(clientSn2payPaymentNo);
        if (payDeal == null || StringUtils.isBlank(payDeal.getPayPaymentNo())) {
            log.info("收钱吧回调数据中支付平台流水号对应支付数据不存在 " + JSON.toJSONString(cmNotify));
            throw new BusinessException(ExceptionStatus.E2001004.getCode(), ExceptionStatus.E2001004.getMessage());
        }

        PayAssert.notNull(orderStatus, ExceptionStatus.E2001006.getCode(), "收钱吧[orderStatus]:[支付回调结果参数为空]");
        if (orderStatus.equals(CmBizOrderStatus.PAID.getCode())) {
            this.paySuccess(payDeal, cmNotify);
        } else if (orderStatus.equals(CmBizOrderStatus.PAY_CANCELED.getCode())) {
            log.info("clientSn2payPaymentNo {} 支付结果支付失败。", clientSn2payPaymentNo);
            this.payFail(payDeal, cmNotify);
//            this.sendFailEmail(clientSn2payPaymentNo);
        } else if (orderStatus.equals(CmBizOrderStatus.PAY_ERROR.getCode())) {
            log.info("clientSn2payPaymentNo {} 支付结果不明，需要收钱吧 人工处理。", clientSn2payPaymentNo);
//            this.sendErrorEmail(clientSn2payPaymentNo);
        } else {
            throw new BusinessException(ExceptionStatus.E2001009.getCode(), "收钱吧:[支付回调结果参数异常]");
        }
    }

    /**
     *
     * @param clientSn2payPaymentNo
     */
    private void sendErrorEmail(String clientSn2payPaymentNo) {
        StringBuilder content = new StringBuilder("paymentNo 【 " + clientSn2payPaymentNo + " 】支付出错，支付结果不明，可能需要收钱吧人工处理。");
        log.info("异步发送邮件 content is " + content);
        PayEventBus.post(new EmailModel(content.toString(), "收钱吧订单支付失败", emailConfig.financeReceivers()));
    }

    private void sendFailEmail(String clientSn2payPaymentNo) {
        StringBuilder content = new StringBuilder("paymentNo 【 " + clientSn2payPaymentNo + " 】 用户支付失败，请知晓。");
        log.info("异步发送邮件 content is " + content);
        PayEventBus.post(new EmailModel(content.toString(), "收钱吧订单支付失败", emailConfig.financeReceivers()));
    }

    /**
     * @param payDeal
     * @param cmNotify
     */
    private void paySuccess(PayDeal payDeal, CmNotifyRequest cmNotify) {

        PayDeal pd = new PayDeal();
        pd.setPayId(payDeal.getPayId());
        //数据库支付记录已修改为支付成功
        if (payDeal.getPayStatus() == PayStatus.PAY_SUCCESS.getValue()) {
            log.info("支付流水号 {} 支付结果重复回调 : " + JSON.toJSONString(cmNotify), payDeal.getPayPaymentNo());
            return;
        }

        //成功回调时,如果数据库支付记录状态不是成功 则修改为成功,
        if (payDeal.getPayStatus() != PayStatus.PAY_SUCCESS.getValue()) {
            pd.setPayStatus(PayStatus.PAY_SUCCESS.getValue());
            pd.setOperateStatus(OperateStatus.PAYMENT_CALLBACK.getCode());
            String sn = cmNotify.getSn();
            String totalAmount = cmNotify.getTotal_amount();
            PayAssert.notNull(sn, ExceptionStatus.E2001004.getCode(), ExceptionStatus.E2001004.getMessage());
            PayAssert.notNull(totalAmount, ExceptionStatus.E2001009.getCode(), ExceptionStatus.E2001009.getMessage());

            log.info("支付平台流水号-{}, 第三方支付平台流水号-{}。", payDeal.getPayPaymentNo(), sn);

            pd.setChannelTransaction(sn);
            if (StringUtils.isNotBlank(totalAmount)) {
                pd.setReceiveAmount(BigDecimalUtils.fenToYuan(totalAmount));
                if (payDeal.getRequestAmount().compareTo(pd.getReceiveAmount()) != 0) {
                    log.info("订单信息 : {}", JSON.toJSONString(payDeal));
                    log.info("支付平台流水号-[{}] , 订单金额与支付金额不相等 订单金额 : [{}] , 支付金额: [{}]", new String[]{payDeal.getPayPaymentNo(), payDeal.getRequestAmount().toString(), pd.getReceiveAmount().toString()});
                    throw new BusinessException(ExceptionStatus.E2001008.getCode(), ExceptionStatus.E2001008.getMessage());
                }
            } else {
                throw new BusinessException(ExceptionStatus.E2001008.getCode(), "支付金额不能为空");
            }

            log.info("收钱吧 PayPaymentNo-{}, paytime is [" + cmNotify.getFinish_time() + "]", payDeal.getPayPaymentNo());

            pd.setPayTime(new Date(Long.valueOf(cmNotify.getFinish_time())));
            pd.setDoneTime(new Date());

            payBaseService.updPayDeal(pd, payDeal);
        }
    }

    /**
     * @param payDeal
     * @param cmNotify
     */
    private void payFail(PayDeal payDeal, CmNotifyRequest cmNotify) {

        PayDeal pdUpdate = new PayDeal();
        pdUpdate.setPayId(payDeal.getPayId());
        //数据库支付记录已修改为支付失败
        if (payDeal.getPayStatus() == PayStatus.PAY_FAIL.getValue()) {
            log.info("支付流水号 {} 支付结果重复回调 : " + JSON.toJSONString(cmNotify), payDeal.getPayPaymentNo());
            return;
        }
        log.info("收钱吧 支付回调 order_status is : " + cmNotify.getOrder_status());
        //支付失败回调时,如果支付记录状态不是支付失败,则修改为支付失败
        if (payDeal.getPayStatus() != PayStatus.PAY_FAIL.getValue()) {
            pdUpdate.setPayStatus(PayStatus.PAY_FAIL.getValue());
            pdUpdate.setOperateStatus(OperateStatus.PAYMENT_CALLBACK.getCode());
            pdUpdate.setDoneTime(new Date());

            payBaseService.updPayDeal(pdUpdate, null);
        }
    }

}
